﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Threading;

namespace Contra
{
     public class Game1 : Microsoft.Xna.Framework.Game
    {

        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Player player;
        List<Bullet> bullets = new List<Bullet>();
        List<Enemy> enemies = new List<Enemy>();
        float spawn = 0;
        Random random = new Random();
        int killedEnemies;
        List<Enemy> killedEnemiesList;
        SpriteFont Font;
        SpriteFont EndGameFont;
        Vector2 fontPos;
        Vector2 HPfontPos;
        Vector2 gameOver;
        Texture2D background;
        Rectangle mainFrame;
        int enemiesBeforeBoss = 10;
        int totalEnemiesSpawned = 0;
        bool youWon = false;
     

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

      
        protected override void Initialize()
        {
            base.Initialize();
        }

       
        protected override void LoadContent()
        {
            
            spriteBatch = new SpriteBatch(GraphicsDevice);

            player = new Player(new Vector2(100, 100), bullets);
            player.LoadContent(Content);
            Font = Content.Load<SpriteFont>("SpriteFont1");
            EndGameFont = Content.Load<SpriteFont>("EndOfGameFont");
            
            fontPos = new Vector2(650, 20);
            HPfontPos = new Vector2(100,20);
            gameOver = new Vector2( GraphicsDevice.Viewport.Width / 2 - 100,
                                    GraphicsDevice.Viewport.Height / 2);
            background = Content.Load<Texture2D>("desert");
            mainFrame = new Rectangle(0, 0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);

            
     
        }

        public void LoadEnemies()
        {
            if (totalEnemiesSpawned < enemiesBeforeBoss)
            {
                int randY = random.Next(100, 400);

                if (spawn >= 1)
                {
                    spawn = 0;
                    if (enemies.Count() < 4)
                    {
                        enemies.Add(MonsterFactory.GetRegularEnemy(Content));
                        totalEnemiesSpawned++;
                    }
                }
                for (int i = 0; i < enemies.Count; i++)
                {
                    if (!enemies[i].IsVisible)
                    {
                        enemies.RemoveAt(i);
                        i--;
                    }
                }
            }
            if (killedEnemies == enemiesBeforeBoss)
            {                            
                
                enemies.Add(MonsterFactory.GetBoss(Content, graphics.GraphicsDevice));
                killedEnemies = 0;
            }
        }
     
        protected override void UnloadContent()
        {
        }

        public void UpdateBullets()
        {
            foreach (var bullet in bullets)
            {
                bullet.position += bullet.velocity;
                if (Vector2.Distance(bullet.position, player.sPosition) > 800)
                {
                    bullet.isVisible = false;
                }
            }
            for (int i = 0; i < bullets.Count; i++)
            {
                if (!bullets[i].isVisible)
                {
                    bullets.RemoveAt(i);
                    i--;
                }
            }
        }

   
        

        public void CheckForCollision()
        {
           killedEnemiesList = new List<Enemy>();

            if (enemies.Count > 0)
            {
                for (int i = 0; i < enemies.Count; i++)
                {
                    if (bullets.Count > 0)
                    {
                         for (int j = 0; j < bullets.Count; j++)
                         {                   
                            if (enemies[i].enemyRec.Intersects(bullets[j].BulletRec))
                            {
                                enemies[i].GotHit();
                                if (!enemies[i].IsAlive)
                                {
                                    killedEnemies++;
                                    killedEnemiesList.Add(enemies[i]);
                                }
                                bullets.RemoveAt(j);
                            }
                          
                         }
                    }
                }

            }

            foreach (Enemy en in killedEnemiesList)
            {
                enemies.Remove(en);
                if (en.GetType() == typeof(Boss))
                {
                    youWon = true;
                }
            }

          
            if (enemies.Count > 0 )
            {
                for (int i = 0; i < enemies.Count; i++)
                {

                    for (int j = 0; j < enemies[i].bullets.Count; j++)
                    {
                        if (player.characterRec.Intersects(enemies[i].enemyRec) || player.characterRec.Intersects(enemies[i].bullets[j].BulletRec))
                        {
                            player.GotHit();
                            if (!player.IsAlive)
                            {
                            }
                            else
                            {
                                player.sPosition = new Vector2(100, 100);
                                enemies[i].bullets.RemoveAt(j);
                            }
                        }
                    }
                }
             }
        }
        protected override void Update(GameTime gameTime)
        {
        
            spawn += (float)gameTime.ElapsedGameTime.TotalSeconds;

            foreach(Enemy enemy in enemies)
            {
                enemy.UpDate(graphics.GraphicsDevice, gameTime);
            }

           
            foreach (var i in bullets)
            {
                i.UpDate();
            }
            

            for (int i = 0;i < enemies.Count; i++)
            {
                foreach(var j in enemies[i].bullets)
                {
                    j.UpDate();
                }
            }
            
            LoadEnemies();
            UpdateBullets();
            player.UpDate(gameTime);
         
            CheckForCollision();

            base.Update(gameTime);
        }


        public void InitLost()
        {
            bullets.Clear();
            enemies.Clear();
            player.sPosition = new Vector2(-100, -100);

            string gOver = "Game OVER";
            Vector2 FontOrigin = Font.MeasureString(gOver) / 2;

            Rectangle backGroundLost = new Rectangle(0, 0, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight);
            Texture2D lostTexture = Content.Load<Texture2D>("terranlost");
            spriteBatch.Draw(lostTexture, backGroundLost, Color.White);
            spriteBatch.DrawString(EndGameFont, gOver, gameOver, Color.White,
            0, FontOrigin, 1.0f, SpriteEffects.None, 0.5f);
        }


        public void InitWin()
        {
            bullets.Clear();
            enemies.Clear();
            player.sPosition = new Vector2(-100, -100);

            string won = "Victory !!!";
            Vector2 FontOrigin = Font.MeasureString(won) / 2;

            Rectangle backGroundLost = new Rectangle(0, 0, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight);
            Texture2D lostTexture = Content.Load<Texture2D>("terranwin");
            spriteBatch.Draw(lostTexture, backGroundLost, Color.White);
            spriteBatch.DrawString(EndGameFont, won, gameOver, Color.White,
            0, FontOrigin, 1.0f, SpriteEffects.None, 0.5f);
        }
       
        protected override void Draw(GameTime gameTime)
        {


            GraphicsDevice.Clear(Color.CornflowerBlue);
          

            spriteBatch.Begin();
            spriteBatch.Draw(background, mainFrame, Color.White);



            string output = "Enemies killed : "+killedEnemies;
            string HP = "Current HP : " + player.hitPoints;
            Vector2 FontOrigin = Font.MeasureString(output) / 2;



            spriteBatch.DrawString(Font, output, fontPos, Color.Black,
                0, FontOrigin, 1.0f, SpriteEffects.None, 0.5f);

            spriteBatch.DrawString(Font, HP, HPfontPos, Color.Black,
                0, FontOrigin, 1.0f, SpriteEffects.None, 0.5f);

            if (player.hitPoints == 0)
            {
                InitLost();
            }

            if (youWon)
            {
                InitWin();
            }

        
   

            player.Draw(spriteBatch);
           
            foreach (var bullet in bullets)
            {
                bullet.Draw(spriteBatch);
            }

            foreach (var enemy in enemies)
            {
                enemy.Draw(spriteBatch);
            }
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}
